#include "funcionesSelect.h"
#include "raid.h"

void nodoSelect_crear(struct listaSelect **punteroEstructura, int32_t descriptor){
	*punteroEstructura=calloc(1,sizeof(struct listaSelect));
	(*punteroEstructura)->descriptor=descriptor;
	(*punteroEstructura)->tipo=-1;
	(*punteroEstructura)->status=-1;
	(*punteroEstructura)->punteroBackup=NULL;
	(*punteroEstructura)->punteroBackupFin=NULL;
	(*punteroEstructura)->cantidadPedido=0;
	memset((*punteroEstructura)->identificadorPPD,'\0',20);
	(*punteroEstructura)->siguiente=NULL;
}


void colaSelect_meter(struct listaSelect **punteroFte,struct listaSelect **punteroFin, struct listaSelect **punteroEstructura)
{
	if(*punteroFte==NULL)
		{
			*punteroFte=*punteroEstructura;
		}
	else
		{
		pthread_mutex_lock(&mutexPtroSelectAux);
			(*punteroFin)->siguiente=*punteroEstructura;
		pthread_mutex_unlock(&mutexPtroSelectAux);
		}
	*punteroFin=*punteroEstructura;
}

// el int32_t valor sería el numero de sector a eliminar
void nodoDeColaSelect_eliminar(struct listaSelect **punteroFte,struct listaSelect **punteroFin,struct listaSelect **punteroAux,int32_t descriptor) {
	listaSelect *auxiliar;
	listaSelect *anterior;
	auxiliar = *punteroFte;
	while(auxiliar && (auxiliar->descriptor != descriptor)) {
		anterior = auxiliar;
		auxiliar = auxiliar->siguiente;
	}
	if (*punteroFte == auxiliar){
		pthread_mutex_lock(&mutexPtroFteSelectAux);
		*punteroFte = (*punteroFte)->siguiente;
		pthread_mutex_unlock(&mutexPtroFteSelectAux);
		*punteroAux=*punteroFte;
	}else{
		pthread_mutex_lock(&mutexPtroSelectAux);
		anterior->siguiente = auxiliar->siguiente;
		pthread_mutex_unlock(&mutexPtroSelectAux);
		*punteroAux=anterior;

	}
	if(auxiliar==*punteroFin){
			*punteroFin=anterior;
		}
	if(auxiliar->punteroBackup!=NULL){
		nodoColaLecturaBackup_liberar(&(auxiliar->punteroBackup),&(auxiliar->punteroBackupFin));

	}
	free(auxiliar);
	auxiliar=NULL;


	return;
}


void nodoColaLecturaBackup_liberar(struct estructuraLeer **punteroFrente,struct estructuraLeer **punteroFin)
{

	struct estructuraLeer *punteroListaAuxiliar;
		while (*punteroFin!=NULL)
			{
			punteroListaAuxiliar=*punteroFrente;
			(*punteroFrente)=(*punteroFrente)->siguiente;
			printf("%d\n",punteroListaAuxiliar->numeroSector);
			if(*punteroFrente==NULL)
				{
				*punteroFin=NULL;
				}
			free(punteroListaAuxiliar);
			punteroListaAuxiliar=NULL;
			}

	return;
}


void colaSelect_liberar(struct listaSelect **punteroFrente,struct listaSelect **punteroFin)
{
	struct listaSelect *punteroListaAuxiliar;
	while (*punteroFin!=NULL)
		{
		punteroListaAuxiliar=*punteroFrente;
		(*punteroFrente)=(*punteroFrente)->siguiente;
		printf("%d\n",punteroListaAuxiliar->descriptor);
		if(*punteroFrente==NULL)
			{
			*punteroFin=NULL;
			}
		free(punteroListaAuxiliar);
		punteroListaAuxiliar=NULL;
		}
}
void clienteNuevo_agregar (int servidor, struct listaSelect **punteroFteSelect,struct listaSelect **punteroFinSelect) {

	struct listaSelect *punteroEstructura;

	nodoSelect_crear(&punteroEstructura, conexionCliente_Aceptar (servidor));
	colaSelect_meter(&(*punteroFteSelect),&(*punteroFinSelect), &punteroEstructura);
	printf ("Aceptado cliente %d\n", (*punteroFinSelect)->descriptor);
	return;
}
int descriptorMaximo_detectar (struct listaSelect **punteroFteSelect,struct listaSelect **punteroFinSelect) {
	struct listaSelect *punteroAux=*punteroFteSelect;
	int max;
	if (punteroAux == NULL)
					return 0;
	max = punteroAux->descriptor;
	while(punteroAux != NULL) {
		if (punteroAux->descriptor > max)
									max = punteroAux->descriptor;
		punteroAux=punteroAux->siguiente;
	}
	return max;
}
void descriptoresCaidos_detectar (struct listaSelect **punteroFteSelect,struct listaSelect **punteroFinSelect) {
	struct listaSelect *punteroAux=*punteroFteSelect;

	if (*punteroFteSelect == NULL)
					return;
	while(punteroAux!=NULL) {
		if (punteroAux->descriptor != -1) {
			punteroAux=punteroAux->siguiente;
		} else {
			if(memcmp(punteroAux->identificadorPPD,identificadorPPDSincro,strlen(identificadorPPDSincro))==0){
				pthread_mutex_lock(&mutexSincro);
				sincronizador=0;
				pthread_mutex_unlock(&mutexSincro);
			}

			struct estructuraLeer *punteroAuxiliarBackup;
			struct estructuraLeer *punteroEstructuraLeer;
			punteroAuxiliarBackup=punteroAux->punteroBackup;
			while(punteroAuxiliarBackup){
				nodoLectura_crear(&punteroEstructuraLeer,punteroAuxiliarBackup->numeroSector, punteroAuxiliarBackup->sincro);
				colaLectura_meter(&punteroFrenteLeer,&punteroFinLeer, &punteroEstructuraLeer);
				punteroAuxiliarBackup=punteroAuxiliarBackup->siguiente;
			}

			nodoDeColaSelect_eliminar(&(*punteroFteSelect),&(*punteroFinSelect),&punteroAux,punteroAux->descriptor);
		}
	}
	if (planificadores_buscar()==0){
		//cerrar conexion
		printf("No hay ningun planificador conectado, se cerrara la conexion\n");
		close(socketServidor);
		sleep(3);
		pthread_mutex_lock(&mutexFinalizar);
			finalizar=1;
		pthread_mutex_unlock(&mutexFinalizar);
		pthread_exit(NULL);



	}
}
int planificadores_buscar(){
	struct listaSelect *punteroAux=punteroFteSelect;
	if (punteroFteSelect == NULL){
		return 0;
	}
	while(punteroAux!=NULL) {
		if ((punteroAux->tipo == -1)||(punteroAux->tipo == 0)) {
			return 1;
		}else if(punteroAux->tipo == 1){
			if(punteroAux->siguiente == NULL){
				return 0;
			}else{
				punteroAux=punteroAux->siguiente;
			}
		}
	}
}
